﻿package com.victim.snake.snake
{
	import com.victim.snake.snake.Body;
	import com.victim.snake.snake.DirectionNode;
	import com.victim.snake.user.User;

	//蛇
	public class Snake{
		private var id:int=-1;
		private var bodys:Array=new Array();	//蛇身体列表
		private var name:String="";	//蛇名字
		private var length:uint=0;	//蛇长度
		private var directionList:Array=new Array();	//方向控制表,过时
		private var moving:int=0;	//每次转向后移动的次数
		private var speed:int=0;	//速度
		private var userCurrent:Boolean=false;	//是否为当前玩家自己的蛇
		private var enterFrameMove:Boolean=true;	//是否响应帧频移动事件
		private var death:Boolean=false;	//是否死亡		
		private var modifiedX:int=0;	//预测拉扯值X
		private var modifiedY:int=0;	//预测拉扯值Y
		private var headIndex:int=0;	//蛇头标志位
		private var style:SnakeStyle=null;	//蛇的样式
		

		//初使化蛇 id:id, name:名字 , length:长度 , x:X轴位置 , y:Y轴位置 , w:每节身体宽度 , h:每节身体高度 , color:身体颜色 , direction:方向 , speed:速度 , style:蛇样式
		public function Snake(id:int,name:String,length:uint,x:Number,y:Number,w:Number,h:Number,color:uint,direction:uint,speed:uint,style:String){
			this.name=name;	//初使化蛇名字
			this.id=id;
			this.speed=speed;
			this.style=SnakeStyle.getStyle(style);
			
			//按指定长度创建蛇身体,添加到蛇身体列表
			for (var i=0; i<length; i++)
			{
				//按指定方向初使化蛇身体
				switch (direction)
				{
					case Body.up :
						bodys[i]=new Body(x,y+i*h,w,h,color,direction,i);
						break;
					case Body.down :
						bodys[i]=new Body(x,y-i*h,w,h,color,direction,i);
						break;
					case Body.left :
						bodys[i]=new Body(x+i*w,y,w,h,color,direction,i);
						break;
					case Body.right :
						bodys[i]=new Body(x-i*w,y,w,h,color,direction,i);
						break;
				}
			}
			
			//初使化蛇头蛇尾标志位
			this.headIndex=0;

		};
		
				
		
		//增长身体
		public function grow(growLength:int):void{
			var lbody:Body=this.getHead();
			this.bodys.push(new Body(lbody.getX(),lbody.getY(),lbody.getWidth(),lbody.getHeight(),lbody.getColor(),lbody.getDirection(),lbody.getSerial()));
		}
		
		//加速度
		public function acceleration(speed:int):void{
			this.speed>3?this.speed-=speed:this.speed;
		}
		
		
		//移动蛇（将蛇的最后一个身体移到第一个身体位置）
		public function moveByCoordinate():void{			
			//如果蛇响应帧频事件，循环蛇身体列表,移动蛇
			if(this.enterFrameMove){
				
				/*
				//将蛇后一个身体移到前面一个身体的位置
				for(var i:int=(bodys.length-1);i>0;i--){				
					var fbody:Body=Body(Body(this.bodys[i-1]));
					var body:Body=Body(bodys[i]);
					body.moveByCoordinate(fbody.getX(),fbody.getY());	//将蛇后一个身体移到前面一个身体的位置
				};		
				
				Body(this.getHead()).move();	//移动蛇头				
				*/
				//trace("准备拉扯:"+this.headIndex+"  "+this.tailIndex+"   "+this.getHead().getX()+"  "+this.getHead().getY());
				
				//将蛇的最后一个身体移到第一个身体位置，将蛇头标志位指向这个身体,并重设蛇尾标志位				
				this.getTail().moveByCoordinate(this.getHead().getX(),this.getHead().getY());	//将蛇尾移到蛇头位置
				this.getTail().setDirection(this.getHead().getDirection());	//设置尾的移动方向为蛇头的移动方向
				this.getTail().setIsTrun(false);	//设置身体为非转向身体
				this.headIndex=this.headIndex>0?this.headIndex-1:this.bodys.length-1;	//设置新的蛇头位置(蛇尾设为蛇头)				
				Body(this.getHead()).move();	//移动蛇头				
				
				//trace("拉扯中:"+this.headIndex+"  "+this.tailIndex+"   "+this.getHead().getX()+"  "+this.getHead().getY());
				this.moving+=1;	//移动距离(次数)加1
			}
		}
		
		//预测拉扯(准同步)
		public function fullPlesiochronous():void{
			
			User.getPlaySprite().setText(" 拉扯值:"+this.modifiedX+"  "+this.modifiedY);
			
			
			var i:int=0;
			for(i=0;i<this.modifiedX;i++){
				this.moveByCoordinate();
			}
			for(i=0;i<this.modifiedY;i++){
				this.moveByCoordinate();
			}
			this.modifiedX=0;
			this.modifiedY=0;
			
		}
		
		//设置蛇方向
		public function setDirection(direction:uint):void{
			var body:Body=this.getHead();	//引用蛇头
			body.setDirection(direction);	//设置蛇头方向
			this.moving=0;	//转向后移动距离重置
			//}
		};
		
		
		//判断方向是否为有效方向(不为当前方向的反方向)
		public function isEffectiveDirection(direction:uint):Boolean{
			var body:Body=this.getHead();	//引用蛇头
			return direction!=(body.getDirection()>38?body.getDirection()-2:body.getDirection()+2);
		}
		
		//给出蛇的位置及方向关键坐标系列	返回值:头下标;头方向;头X坐标;头Y坐标;[转向身体下标;转身身体方向;]
		public function getCoordinates():String{
			var coordinates:String="";
			coordinates+=this.headIndex+";"+this.getHead().getDirection()+";"+this.getHead().getX()+";"+this.getHead().getY()+";";	//头方向及坐标
			
			//循环每节身体(从当前蛇头开始)
			for(var i:int=0;i<this.bodys.length;i++){
				var bodyIndex:int=(this.headIndex+i)<this.bodys.length?this.headIndex+i:Math.abs(this.headIndex+i-this.bodys.length);	
				var fBodyIndex:int=bodyIndex==this.bodys.length-1?0:bodyIndex+1;
				//trace(bodyIndex+" "+fBodyIndex);
				
				var lBody:Body=this.bodys[bodyIndex];	//前一个身体
				var fBody:Body=this.bodys[fBodyIndex];	//后一个身体
				
				//如果前一个身体和后一个身体方向不相同
				if(lBody.getDirection()!=fBody.getDirection()&&lBody!=this.getTail()){
					coordinates+=fBodyIndex+";"+fBody.getDirection()+";";	//关键身体方向(转身节的方向)
					//trace(fBodyIndex+";"+fBody.getDirection()+";"+fBody.getX()+";"+fBody.getY()+";");
				}
				
			}
			
			//trace("上传消息:"+coordinates);
			return coordinates;
		}
		
				
		//按蛇的位置及方向关键坐标系列设置蛇的位置
		public function setCoordinates(coordinates:Array):void{	
			
			//计算预测拉扯值
			//User.getPlaySprite().setText((coordinates[0]-this.getX())+"   "+(coordinates[1]-this.getY()));
			modifiedX=Math.abs(int(coordinates[2])-this.getX())/this.getHead().getWidth();
			modifiedY=Math.abs(int(coordinates[3])-this.getY())/this.getHead().getHeight();
			
			

			//如果当前蛇位置和服务器传来的要转向的蛇位置不相等, 重设蛇坐标			
			this.headIndex=coordinates[0];	//设置蛇头
			this.getHead().moveByCoordinate(coordinates[2],coordinates[3]);	//设置蛇头位置
			this.getHead().setDirection(coordinates[1]);	//设置转向前蛇头方向
			
			
			//循环每节身体(从当前蛇头开始)
			for(var i:int=0;i<this.bodys.length-1;i++){
				var bodyIndex:int=(this.headIndex+i)<this.bodys.length?this.headIndex+i:Math.abs(this.headIndex+i-this.bodys.length);	
				var fBodyIndex:int=bodyIndex==this.bodys.length-1?0:bodyIndex+1;			
				
				//trace(bodyIndex+" "+fBodyIndex);
				
				var lBody:Body=this.bodys[bodyIndex];	//前一个身体
				var fBody:Body=this.bodys[fBodyIndex];	//后一个身体
				switch (lBody.getDirection()){
					case Body.up :
						fBody.moveByCoordinate(lBody.getX(),lBody.getY()+lBody.getHeight());
						fBody.setDirection(Body.up);
						break;
					case Body.down :
						fBody.moveByCoordinate(lBody.getX(),lBody.getY()-lBody.getHeight());
						fBody.setDirection(Body.down);
						break;
					case Body.left :
						fBody.moveByCoordinate(lBody.getX()+lBody.getWidth(),lBody.getY());
						fBody.setDirection(Body.left);
						break;
					case Body.right :
						fBody.moveByCoordinate(lBody.getX()-lBody.getWidth(),lBody.getY());
						fBody.setDirection(Body.right);
						break;
				}
				
				//循环关键转向列表的关键点
				for(var reIndex:int=4;reIndex<coordinates.length;reIndex+=2){
					if(fBodyIndex==int(coordinates[reIndex])){	//如果是关键点
						//trace("当前身体:"+fBodyIndex+"  关键身体:"+coordinates[reIndex]);
						switch (uint(coordinates[reIndex+1])){
							case Body.up :
								fBody.moveByCoordinate(lBody.getX(),lBody.getY()+lBody.getHeight());
								fBody.setDirection(Body.up)
								break;
							case Body.down :
								fBody.moveByCoordinate(lBody.getX(),lBody.getY()-lBody.getHeight());
								fBody.setDirection(Body.down)
								break;
							case Body.left :
								fBody.moveByCoordinate(lBody.getX()+lBody.getWidth(),lBody.getY());
								fBody.setDirection(Body.left)
								break;
							case Body.right :
								fBody.moveByCoordinate(lBody.getX()-lBody.getWidth(),lBody.getY());
								fBody.setDirection(Body.right)
								break;
						}
					}
				}			
				
			}
			
			/*for each(var b:Body in this.bodys){
					trace(b.getSerial()+" "+b.getX()+" "+b.getY()+" "+ b.getDirection());
			}*/
			
			//this.getHead().setDirection(coordinates[coordinates.length-1]);	//设置转向方向
			
		}
		
		//自动设置方向,返回蛇的转向方向
		public function autoSetDirection():uint{
			//电脑蛇离最近食物的距离
			var xDistance:Number=100000;	//x距离（可能为负）
			var yDistance:Number=100000;	//y距离（可能为负）
			var absXDistance:Number=0;	//x绝对距离
			var absYDistance:Number=0;	//y绝对距离
			var distance:Number=10000;		//绝对距离
			var direction:uint=0;	//要移动的方向
			var oldDirection:uint=this.getHead().getDirection();	//原方向
			
			
			//循环食物(找出离电脑蛇最近的食物)
			for each(var food:Food in User.getPlaySprite().snakeGraphics.getFoods()){
				var x:Number=this.getHead().getX()-food.getX();
				var y:Number=this.getHead().getY()-food.getY();
				var d:Number=Math.abs(x)+Math.abs(y);
				if(d<distance){
					xDistance=x;
					yDistance=y;
					distance=d;
				}											
			}
										
			//计算绝对距离
			absXDistance=Math.abs(xDistance);
			absYDistance=Math.abs(yDistance);
			
			//trace(("xDistance:"+x)+"  "+("yDistance:"+y));			
			
			
			
			if(xDistance>0){	//如果可以向左
				direction=Body.left
			}
				
			if(direction==0 && xDistance<0){	//如果可以向右
					direction=Body.right;
			}
				
			if(direction==0 && yDistance>0){
					direction=Body.up;
			}				
				
			if(direction==0 && yDistance<0){
				direction=Body.down;
			}
			
			if(direction==0 && xDistance==0 && this.getHead().getX()>400){
				direction=Body.left;
			}
			
			if(direction==0 && xDistance==0 && this.getHead().getX()<400){
				direction=Body.right;
			}
			
			if(direction==0 && yDistance==0 && this.getHead().getX()>240){
				direction==Body.up;
			}
			
			if(direction==0 && yDistance==0 && this.getHead().getX()<240){
				direction==Body.down;
			}			
			
			
			direction=direction==0?this.getHead().getDirection():direction;
			
			if(this.getHead().getDirection()!=direction){	//如果不为当前方向
				this.setDirection(direction);	//设置方向
				this.getHead().setIsTrun(true);
			}
			
			for(var i:uint=0;i<3;i++){
				//如果不会出界或碰撞,并且转向值合理(不为当前方向的反方向)
				if(this.isEffectiveDirection(direction) && !User.getPlaySprite().outOfBounds(this.getHead()) && !User.getPlaySprite().isOverlappingSnakes(this)){
					return direction;
				}else{	//否则换个方向					
					direction==Body.down?direction=Body.left:direction++;
					this.setDirection(direction);
					
					//如果方向为原方向，标记为非转向
					//trace(oldDirection+"  "+direction);
					if(oldDirection==direction){
						this.getHead().setIsTrun(false);
					}else{
						this.getHead().setIsTrun(true);
					}
				}
			}
			return direction;
		}
		
		//get and set
		public function getHead():Body{
			return this.bodys[this.headIndex];
		}
		
		public function getTail():Body{
			return this.bodys[this.headIndex>0?this.headIndex-1:this.bodys.length-1];
		}
		
		public function getSpeed():int{
			return this.speed;
		}
		
		public function getX():int{
			return this.getHead().getX();			
		}
		
		public function setX(x:Number){
//			var rx:int =x-Body(bodys[0]).getX();			
			this.getHead().setX(x);
			/*for(var i:int=1;i<bodys.length;i++){
				Body(bodys[i]).setX(Body(bodys[i]).getX()+rx);
			}*/
		}
		
		public function getY():int{
			return this.getHead().getY();
		}
		
		public function setY(y:Number){
			//var ry:int =y-Body(bodys[0]).getY();
			this.getHead().setY(y);
			/*for(var i:int=1;i<bodys.length;i++){
				Body(bodys[i]).setY(Body(bodys[i]).getY()+ry);
			}*/
		}
		
		public function getName():String{
			return this.name
		};
		
		public function setName(name:String):void{
			this.name=name;
		};
		
		public function getId():int{
			return this.id
		};
		
		public function setId(id:int):void{
			this.id=id;
		};
		
		public function getBodys():Array{
			return this.bodys;
		};
		
		public function getMoving():int{
			return this.moving;
		};
		
		public function setUserCurrent(userCurrent:Boolean):void{
			this.userCurrent=userCurrent;
		};
		
		public function setEnterFrameMove(enterFrameMove:Boolean):void{
			this.enterFrameMove=enterFrameMove;
		};
		
		public function getEnterFrameMove():Boolean{
			return this.enterFrameMove;
		};
		
		public function setDeath(death:Boolean):void{
			this.death=death;
		};
		
		public function getDeath():Boolean{
			return this.death;
		}
		
		public function setStyle(style:SnakeStyle):void{
			this.style=style;
		};
		
		public function getStyle():SnakeStyle{
			return this.style;
		}
		
	};

};